package com.rachel.pickerview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;

import java.util.List;


/**
 * Created by zhengshaorui on 2017/7/5.
 */

public class PickerView extends View {
    private static final String TAG = "zsr";
    private static final int UP_TEXT = -1;
    private static final int DOWN_TEXT = 1;

    public static final int SCROLL_UP = 1;
    public static final int SCROLL_DOWN = 2;

    private static final int PICKER_MOVE = 1;
    private static final int PICKER_UP = 2;
    private static final int PICKER_DOWN = 3;


    private int mWidth,mHeight;
    private Paint mTextPaint;
    private Paint mPaint;
    private int mLine = 120;
    private int mText = 30;
    private List<String> mDatas;
    private int mSelectPos ; //默认的被选中的位置
    private int mVisiableItme = 3; //可见长度为3
    private int mBothTextWidth ; //两个文字之间的宽度
    private float mMoveLength = 0; //手指滑动的距离


    private int mMaxTextSize = 50;
    private int mMinTextSize = 25;

    private Scroller mScroller;
    private int mMaxTextAlpha = 255;
    private int mMinTextAlpha = 120;
    private boolean isFocused = true;  //用来实现是否实现两边，这个主要是Android tv，遥控器获取焦点时使用，手机默认为true即可

    private int runSpeed = 2; //回滚到中间的速度

    boolean isUpEnd = true;  //防止连按滚动异常
    boolean isDownEnd = true;
    private float lastY;

    private Handler mHandler = new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case PICKER_MOVE:
                    if (Math.abs(mMoveLength) < 2){ //让它居中
                        mMoveLength = 0;
                        removeMessages(PICKER_MOVE);

                    }else{
                        mMoveLength = mMoveLength - mMoveLength / Math.abs(mMoveLength) * runSpeed;
                        mHandler.sendEmptyMessageDelayed(PICKER_MOVE,10);
                    }
                    invalidate();
                    break;
            }
        }
    };

    /**
     * 设置选中监听
     */
    public interface  SelectListener<T>{
        void selectedData(T data);
    }
    private SelectListener mSelectListener;

    public void setSelectListener(SelectListener listener){
        mSelectListener = listener;
    }


    public PickerView(Context context) {
        this(context,null);
    }

    public PickerView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
        this.setClickable(true);
        this.setFocusable(true);
        this.setFocusableInTouchMode(true);
        this.setWillNotDraw(false);  //防止ondraw不执行
        init();
    }


    public PickerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 初始化设置画笔等
     */
    private void init() {
        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setColor(Color.BLACK);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(getResources().getColor(R.color.colorAccent));

        mScroller = new Scroller(getContext());

    }



    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        //绘制中间部分
        float scale = mathPowScale(mHeight / 4.0f, mMoveLength);
        float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
        mTextPaint.setTextSize(size);

        mTextPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));

        //mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));


        //绘制文字
        float x = mWidth/2;
        Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
        float textheight = (metrics.descent + metrics.ascent);
        float baseline =  mHeight/2 - textheight/2 + mMoveLength; //通过改变baseline绘制文字

        canvas.drawText(mDatas.get(mSelectPos), x, baseline, mTextPaint);

        //绘制两边
        if (isFocused) {
            for (int i = 1; i < mSelectPos; i++) {
                drawText(canvas, i, UP_TEXT);
            }
            for (int i = 1; i < mDatas.size() - mSelectPos; i++) {
                drawText(canvas, i, DOWN_TEXT);
            }
        }

    }


    /**
     * 获取到焦点时，才把两边的绘制显示出来
     * @param focus
     */
    public void setFocusStatus(boolean focus){
        isFocused = focus;
        invalidate();
    }

    /**
     * 绘制文字
     * @param canvas
     * @param i
     * @param type
     */
    private void drawText(Canvas canvas, int i, int type) {

        float d = mBothTextWidth * i + mMoveLength * type;  //需要滚动的距离
        float scale = mathPowScale(mHeight / 4.0f, d);

        float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
        mTextPaint.setTextSize(size);
        mTextPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));


        float x = (mWidth )/2;
        //绘制文字
        Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
        float textheight = (metrics.descent + metrics.ascent);
        float baseline =  mHeight/2 - textheight/2 + d * type; //通过改变baseline绘制文字
        canvas.drawText(mDatas.get(mSelectPos + i*type),
                x, baseline, mTextPaint);
    }


    /**
     * scale =  1 -  1/ax^2 {(0< a < height), (-height/2 < x < height/2)}
     * @param a
     * @param x
     * @return 返回一个二元一次函数的变化率
     */
    private float mathPowScale(float a,float x){
        float scale = (float) (1 -  Math.pow(x/a,2));
        return scale < 0 ? 0 : scale;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                lastY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                mMoveLength += (event.getY() - lastY);
                makeViewToCenter();
                lastY = event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //Log.d(TAG, "onTouchEvent: "+Math.abs(mMoveLength));
                mHandler.sendEmptyMessage(PICKER_MOVE);

                break;
        }
       // return true;
        return super.onTouchEvent(event);

    }

    /**
     * 移动头部一个数据到尾部，保持循环
     */
    private void moveHeadToTail()
    {
        String head = mDatas.get(0);
        mDatas.remove(0);
        mDatas.add(head);
    }

    /**
     * 移动尾部一个数据到顶部，保持循环
     */
    private void moveTailToHead()
    {
        String tail = mDatas.get(mDatas.size() - 1);
        mDatas.remove(mDatas.size() - 1);
        mDatas.add(0, tail);
    }


    /**
     * 用方向键实现上下滚动
     * @param direction
     */
    public void setPickerViewMove(int direction){

        if (direction == SCROLL_UP && isUpEnd){
            ValueAnimator animator = ValueAnimator.ofFloat(0,mBothTextWidth);
            animator.setDuration(400);
            animator.setInterpolator(new LinearInterpolator());
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float value = (float) animation.getAnimatedValue();
                    mMoveLength = value;
                    isUpEnd = false;
                    invalidate();
                }
            });
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    makeViewToCenter();
                    isUpEnd = true;
                }
            });
            animator.start();

        }else if (direction == SCROLL_DOWN && isDownEnd){
            ValueAnimator animator = ValueAnimator.ofFloat(0,-mBothTextWidth);
            animator.setDuration(400);
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float value = (float) animation.getAnimatedValue();
                    mMoveLength = value;
                    isDownEnd = false;
                    invalidate();
                }
            });
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    makeViewToCenter();
                    isDownEnd = true;
                }
            });
            animator.start();

        }

    }

    /**
     * 数据抱持移动到中间
     */
    private void makeViewToCenter() {
        //Log.d(TAG, "setPickerViewMove: "+(mMoveLength > mBothTextWidth / 2)+" "+mMoveLength);

        if (mMoveLength > mBothTextWidth/2) {
            moveTailToHead();
            mMoveLength = mMoveLength - mBothTextWidth;
        } else if (mMoveLength < -mBothTextWidth/2) {
            moveHeadToTail();
            mMoveLength = mMoveLength + mBothTextWidth;
        }
    }




    /**
     * 获取数据
     * @param datas
     * @param targetdata
     */
    public void setData(List<String> datas,String targetdata){
        mDatas = datas;

        for (int i = 0; i < datas.size(); i++) {
            if (datas.get(i).equals(targetdata)){
                mSelectPos = i;
                break;
            }
        }

        invalidate();
    }

    /**
     * 获取数据
     * @param <T>
     * @return
     */
    public <T> T getSelectData(){
        /*if (listener != null) {
            listener.selectedData(mDatas.get(mSelectPos));
        }*/
        return (T) mDatas.get(mSelectPos);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mWidth = measureWidth(widthMeasureSpec);
        mHeight = measureHeight(heightMeasureSpec);

        mBothTextWidth = mHeight/mVisiableItme;
        setMeasuredDimension(mWidth, mHeight);


    }

    //设置高的大小
    private int measureHeight(int heightMeasureSpec) {
        // TODO Auto-generated method stub
        int result = 0;
        //获取模式和大小
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 70; //如果是wrap_content ,给个初始值
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    //设置宽的大小
    private int measureWidth(int widthMeasureSpec) {
        // TODO Auto-generated method stub
        int result = 0;
        //获取模式和大小
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 70; //如果是wrap_content ,给个初始值
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }


}
